﻿namespace VK.Lib
{

	/// <summary>
	/// 
	/// </summary>
	public class VKUtils
	{

		/// <summary>
		/// Merges two dictionaries.
		/// </summary>
		/// <param name="first">Default values, only used if second does not contain a value.</param>
		/// <param name="second">Every value of the merged object is used.</param>
		/// <returns>The merged dictionary</returns>
		internal static System.Collections.Generic.IDictionary<TKey, TValue> Merge<TKey, TValue>(System.Collections.Generic.IDictionary<TKey, TValue> first, System.Collections.Generic.IDictionary<TKey, TValue> second)
		{
			first = first ?? new System.Collections.Generic.Dictionary<TKey, TValue>();
			second = second ?? new System.Collections.Generic.Dictionary<TKey, TValue>();

			var merged = new System.Collections.Generic.Dictionary<TKey, TValue>();

			foreach (var kvp in first)
				if (!merged.ContainsKey(kvp.Key))
					merged.Add(kvp.Key, kvp.Value);

			foreach (var kvp in second)
				merged.Add(kvp.Key, kvp.Value);

			return merged;
		}

		/// <summary>
		/// Converts the dictionary to a formatted login string.
		/// </summary>
		/// <param name="dictionary">The dictionary.</param>
		/// <returns>A formatted login string.</returns>
		internal static string ToOAuthClientLoginString(System.Collections.Generic.IDictionary<string, object> dictionary)
		{
			if (dictionary == null)
				throw new System.ArgumentNullException("dictionary");

			// check if client_id is not null or empty.
			if (dictionary["client_id"] == null || string.IsNullOrEmpty(dictionary["client_id"].ToString()))
				throw new System.ArgumentException("client_id required.");

			// check if scope is not null or empty.
			if (dictionary["scope"] == null || string.IsNullOrEmpty(dictionary["scope"].ToString()))
				throw new System.ArgumentException("scope required.");

			// check if display is not null or empty.
			if (dictionary["display"] == null || string.IsNullOrEmpty(dictionary["display"].ToString()))
				dictionary["display"] = "popup";

			// check if redirect_uri is not null or empty.
			if (dictionary.ContainsKey("redirect_uri") == false || dictionary["redirect_uri"] == null || string.IsNullOrEmpty(dictionary["redirect_uri"].ToString()))
				dictionary["redirect_uri"] = "http://api.vk.com/blank.html";

			return string.Format("http://api.vk.com/oauth/authorize?client_id={0}&redirect_uri={2}&scope={1}&display={3}&response_type=token",
																		dictionary["client_id"].ToString().Trim().ToLower(),
																		dictionary["scope"].ToString().Trim().ToLower(),
																		dictionary["redirect_uri"].ToString().Trim().ToLower(),
																		dictionary["display"].ToString().Trim().ToLower());
		}

		/// <summary>
		/// Parse a URL and fragment parameters into a key-value bundle.
		/// </summary>
		/// <param name="query">
		/// The URL to parse.
		/// </param>
		/// <returns>
		/// Returns a dictionary of keys and values for the url string.
		/// </returns>
		public static System.Collections.Generic.IDictionary<string, object> ParseLoginResultString(string query)
		{
			var result = new System.Collections.Generic.Dictionary<string, object>();

			// if string is null, empty or whitespace
			if (string.IsNullOrEmpty(query) || query.Trim().Length == 0)
				return result;

			string decoded = query;
			int decodedLength = decoded.Length;
			int namePos = 0;
			bool first = true;

			while (namePos <= decodedLength)
			{
				int valuePos = -1, valueEnd = -1;
				for (int q = namePos; q < decodedLength; q++)
				{
					if (valuePos == -1 && decoded[q] == '=')
					{
						valuePos = q + 1;
					}
					else if (decoded[q] == '&')
					{
						valueEnd = q;
						break;
					}
				}

				if (first)
				{
					first = false;
					if (decoded[namePos] == '?')
					{
						namePos++;
					}
				}

				string name, value;

				if (valuePos == -1)
				{
					name = null;
					valuePos = namePos;
				}
				else
				{
					name = HttpHelper.UrlDecode(decoded.Substring(namePos, valuePos - namePos - 1));
				}

				if (valueEnd < 0)
				{
					namePos = -1;
					valueEnd = decoded.Length;
				}
				else
				{
					namePos = valueEnd + 1;
				}

				value = HttpHelper.UrlDecode(decoded.Substring(valuePos, valueEnd - valuePos));

				if (!string.IsNullOrEmpty(name))
				{
					result[name] = value;
				}

				if (namePos == -1)
				{
					break;
				}
			}

			return result;
		}

	}

}